#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <vector>

typedef long long ll;

int const P = 998244353, G = 3, iG = 3327118;
int const N = (1 << 20) + 1;

template <typename T>
inline T &read(T &x) {
  x = 0;
  bool f = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = x * 10 + (ch ^ '0'), ch = getchar();
  if (f) x = -x;
  return x;
}

class Polynomial {
 private:
  int f[N];
  static int Cvt[N << 2];

 public:
  void NTT(const bool typ, const int n);
  void inv(Polynomial &res, const int n) const;
  void ln(Polynomial &res, const int n) const;
  void exp(Polynomial &res, const int n) const;
  int &operator[](int index) { return f[index]; };
  const int &operator[](int index) const { return f[index]; };
  inline void pre(int n) {
    for (int i = 1, len = 2; len <= n; ++i, len <<= 1)
      for (int j = 1, *const cvt = Cvt + len - 1; j < len; ++j)
        cvt[j] = cvt[j >> 1] >> 1 | ((j & 1) << (i - 1));
  }
  inline void clear(int n) {
    int maxl = 1;
    while (maxl < n) maxl <<= 1;
    memset(f, 0, sizeof(int) * maxl);
  }
} f, g;

int n;
int Polynomial::Cvt[N << 2];

inline ll qpow(ll base, int exp) {
  ll res = 1;
  while (exp) {
    if (exp & 1) res = res * base % P;
    base = base * base % P;
    exp >>= 1;
  }
  return res;
}

inline void Polynomial::NTT(const bool typ, const int n) {
  for (int i = 1, *const cvt = Cvt + n - 1; i < n; ++i)
    if (i < cvt[i]) std::swap(f[i], f[cvt[i]]);
  for (int i = 2; i <= n; i <<= 1) {
    int mid = i >> 1, wn = qpow(typ ? G : iG, (P - 1) / i);
    for (int j = 0; j < n; j += i) {
      ll wk = 1;
      for (int k = 0; k < mid; ++k, (wk *= wn) %= P) {
        ll t = wk * f[j + k + mid] % P;
        if ((f[j + k + mid] = f[j + k] - t) < 0) f[j + k + mid] += P;
        if ((f[j + k] += t) >= P) f[j + k] -= P;
      }
    }
  }
  if (!typ) {
    ll inv = qpow(n, P - 2);
    for (int i = 0; i < n; ++i) f[i] = inv * f[i] % P;
  }
}

inline void Polynomial::inv(Polynomial &res, const int n) const {
  static Polynomial tmp;
  if (n == 1) return res[0] = qpow(f[0], P - 2), void();
  inv(res, (n + 1) >> 1);
  int maxl = 1;
  while (maxl < n << 1) maxl <<= 1;
  tmp.clear(n << 1);
  memcpy(tmp.f, f, sizeof(int) * n);
  tmp.NTT(true, maxl), res.NTT(true, maxl);
  for (int i = 0; i < maxl; ++i)
    res[i] = static_cast<ll>(res[i]) *
             ((2ll - static_cast<ll>(res[i]) * tmp[i] % P + P) % P) % P;
  res.NTT(false, maxl);
  for (int i = n; i < maxl; ++i) res[i] = 0;
}

inline void Polynomial::ln(Polynomial &res, const int n) const {
  static Polynomial df, invf;
  df.clear(n << 1), invf.clear(n << 1);
  int maxl = 1;
  while (maxl < n << 1) maxl <<= 1;
  for (int i = 0; i + 1 < n; ++i) df[i] = static_cast<ll>(f[i + 1]) * (i + 1) % P;
  inv(invf, n);
  invf.NTT(true, maxl), df.NTT(true, maxl);
  for (int i = 0; i < maxl; ++i) res[i] = static_cast<ll>(df[i]) * invf[i] % P;
  res.NTT(false, maxl);
  for (int i = n - 1; i; --i) res[i] = static_cast<ll>(res[i - 1]) * qpow(i, P - 2) % P;
  res[0] = 0;
}

inline void Polynomial::exp(Polynomial &res, const int n) const {
  static Polynomial lnres;
  if (n == 1) { return res[0] = 1, void(); }
  exp(res, (n + 1) >> 1);
  res.ln(lnres, n);
  int maxl = 1;
  while (maxl < n << 1) maxl <<= 1;
  for (int i = 0; i < n; ++i)
    if ((lnres[i] = f[i] - lnres[i]) < 0) lnres[i] += P;
  ++lnres[0];
  if (lnres[0] >= P) lnres[0] -= P;
  lnres.NTT(true, maxl), res.NTT(true, maxl);
  for (int i = 0; i < maxl; ++i) res[i] = static_cast<ll>(res[i]) * lnres[i] % P;
  res.NTT(false, maxl);
  for (int i = n; i < maxl; ++i) res[i] = 0;
}

namespace polynomials {

typedef std::vector<int> vec;
int w[N], iv[N], r[N], last;

inline void init(int n) {
  int lim = 1;
  while (lim < n) lim <<= 1;
  iv[1] = 1;
  for (int i = 2; i <= lim; i++) iv[i] = (P - 1ll * (P / i) * iv[P % i] % P) % P;
  for (int i = 1; i < lim; i <<= 1) {
    int wn = qpow(G, (P - 1) / (i << 1));
    for (int j = 0, ww = 1; j < i; j++, ww = 1ll * ww * wn % P) w[i + j] = ww;
  }
}

inline void ntt(vec &f, int n, int op) {
  f.resize(n);
  if (last != n) {
    for (int i = 1; i < n; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
    last = n;
  }
  for (int i = 1; i < n; i++)
    if (i < r[i]) std::swap(f[i], f[r[i]]);
  for (int i = 1; i < n; i <<= 1)
    for (int j = 0; j < n; j += i << 1)
      for (int k = 0; k < i; k++) {
        int x = f[j + k], y = 1ll * f[i + j + k] * w[i + k] % P;
        f[j + k] = (x + y) % P;
        f[i + j + k] = (x - y + P) % P;
      }
  if (op == -1) {
    std::reverse(&f[1], &f[n]);
    for (int i = 0; i < n; i++) f[i] = 1ll * f[i] * iv[n] % P;
  }
}

void getinv(vec f, vec &g, int n) {
  static vec x;
  g.resize(n);
  if (n == 1) {
    g[0] = qpow(f[0], P - 2);
    return;
  }
  getinv(f, g, (n + 1) >> 1);
  int lim = 1;
  while (lim < (n << 1)) lim <<= 1;
  x.resize(lim);
  for (int i = 0; i < n; i++) x[i] = f[i];
  for (int i = n; i < lim; i++) x[i] = 0;
  g.resize(lim);
  ntt(x, lim, 1), ntt(g, lim, 1);
  for (int i = 0; i < lim; i++) g[i] = 1ll * g[i] * (2 - 1ll * g[i] * x[i] % P + P) % P;
  ntt(g, lim, -1);
  g.resize(n);
}

namespace evaluation {

vec g[N], f, b;
int n;

void build(int l, int r, int x) {  //计算g
  if (l == r) {
    g[x].resize(2);
    g[x][0] = 1, g[x][1] = P - b[l];
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, x * 2), build(mid + 1, r, x * 2 + 1);
  int lim = 1;
  while (lim < r - l + 2) lim <<= 1;
  g[x].resize(lim);
  ntt(g[x * 2], lim, 1), ntt(g[x * 2 + 1], lim, 1);
  for (int i = 0; i < lim; i++) g[x][i] = 1ll * g[x * 2][i] * g[x * 2 + 1][i] % P;
  ntt(g[x], lim, -1);  //我们做完以后除了g[1]每一个g都是点值形式
  g[x].resize(r - l + 2);
}

vec mulT(vec a, vec b, int n) {
  //除去idft之外的卷积转置，需要保证a和b是个数相同的点值，n是保留的项数
  int lim = a.size();
  for (int i = 0; i < lim; i++) a[i] = 1ll * a[i] * b[i] % P;
  ntt(a, lim, 1);
  return vec(&a[0], &a[n]);  //取a[0]-a[n-1]
}

void solve(int l, int r, int x, vec h) {
  if (l == r) {
    b[l] = h[0];
    return;
  }  //我们把b作为存答案的数组
  int mid = (l + r) >> 1, lim = 1;
  while (lim < (r - l + 2)) lim <<= 1;
  ntt(h, lim, -1);
  solve(l, mid, x * 2, mulT(g[x * 2 + 1], h, mid - l + 1));
  solve(mid + 1, r, x * 2 + 1, mulT(g[x * 2], h, r - mid));
}

inline void evaluate(vec F, vec B, vec &ans, int N) {
  f = F, b = B, n = N;
  build(0, n - 1, 1);
  getinv(g[1], g[1], n);
  int lim = 1;
  while (lim < 2 * n) lim <<= 1;
  ntt(g[1], lim, 1);
  ntt(f, lim, -1);
  solve(0, n - 1, 1, mulT(g[1], f, n));
  ans = b;
}

}  // namespace evaluation

using evaluation::evaluate;
}  // namespace polynomials

using namespace polynomials;
vec a, b, c;

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen64("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen64("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen(".in", "r", stdin);
  freopen(".out", "w", stdout);
#endif
#endif

  int n, m, t;
  ++read(n), read(m);
  t = std::max(n, m);
  init(n + m);
  a.resize(t), b.resize(t);
  for (int i = 0; i < n; ++i) read(a[i]);
  for (int i = 0; i < m; ++i) read(b[i]);
  evaluate(a, b, c, t);
  for (int i = 0; i < m; ++i) printf("%d\n", c[i]);
  return 0;
}